using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Matrix.Configuration.Contracts;
using Matrix.Configuration;
using Matrix.Configuration.DTOs;

namespace Matrix.Configuration.Application.Services
{
    /// <summary>
    /// 配置查询服务
    /// 专门负责所有只读操作，提供高性能的查询能力
    /// </summary>
    public class ConfigurationQueryService : ApplicationService, IConfigurationQueryService
    {
        private readonly IRepository<ConfigurationItem, Guid> _configurationRepository;
        private readonly IDistributedCache<ListResultDto<ConfigurationItemDto>> _cache;
        private readonly ILogger<ConfigurationQueryService> _logger;

        public ConfigurationQueryService(
            IRepository<ConfigurationItem, Guid> configurationRepository,
            IDistributedCache<ListResultDto<ConfigurationItemDto>> cache,
            ILogger<ConfigurationQueryService> logger)
        {
            _configurationRepository = configurationRepository;
            _cache = cache;
            _logger = logger;
        }

        /// <summary>
        /// 通过键名获取配置值（带缓存）
        /// </summary>
        public async Task<ConfigurationItemDto> GetByKeyAsync(GetConfigurationItemInput input)
        {
            var cacheKey = GetCacheKey(input.Key, input.Namespace);

            // 尝试从缓存获取 - 跳过缓存以避免类型不匹配问题
            // var cachedItem = await _cache.GetAsync(cacheKey);
            // if (cachedItem != null)
            // {
            //     _logger.LogDebug("配置从缓存获取成功: {Key}", input.Key);
            //     return cachedItem;
            // }

            // 从数据库获取
            var queryable = await _configurationRepository.GetQueryableAsync();
            var entity = await AsyncExecuter.FirstOrDefaultAsync(
                queryable.Where(x => x.Key == input.Key && x.Namespace == input.Namespace)
            );

            if (entity == null)
            {
                _logger.LogWarning("配置项不存在: {Key}", input.Key);
                throw new Volo.Abp.Domain.Entities.EntityNotFoundException(typeof(ConfigurationItem), input.Key);
            }

            var dto = ObjectMapper.Map<ConfigurationItem, ConfigurationItemDto>(entity);

            // 缓存结果 - 跳过缓存以避免类型不匹配问题
            // var options = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30) };
            // await _cache.SetAsync(cacheKey, dto, options);

            _logger.LogInformation("配置从数据库获取成功: {Key}", input.Key);
            return dto;
        }

        /// <summary>
        /// 通过命名空间获取配置列表
        /// </summary>
        public async Task<ListResultDto<ConfigurationItemDto>> GetByNamespaceAsync(string @namespace)
        {
            var cacheKey = $"namespace_configs:{@namespace}";

            // 尝试从缓存获取
            var cachedItems = await _cache.GetAsync(cacheKey);
            if (cachedItems != null)
            {
                return cachedItems;
            }

            // 从数据库获取
            var queryable = await _configurationRepository.GetQueryableAsync();
            var entities = await AsyncExecuter.ToListAsync(
                queryable.Where(x => x.Namespace == @namespace)
                    .OrderBy(x => x.Category)
                    .ThenBy(x => x.Key)
            );

            var dtos = ObjectMapper.Map<List<ConfigurationItem>, List<ConfigurationItemDto>>(entities);
            var result = new ListResultDto<ConfigurationItemDto>(dtos);

            // 缓存结果
            var cacheOptions = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15) };
            await _cache.SetAsync(cacheKey, result, cacheOptions);

            return result;
        }

        /// <summary>
        /// 检查配置是否存在
        /// </summary>
        public async Task<bool> ExistsAsync(GetConfigurationItemInput input)
        {
            // 检查数据库
            var queryable = await _configurationRepository.GetQueryableAsync();
            var exists = await AsyncExecuter.AnyAsync(
                queryable.Where(x => x.Key == input.Key && x.Namespace == input.Namespace)
            );

            return exists;
        }

        /// <summary>
        /// 获取类型化配置值
        /// </summary>
        public async Task<T> GetTypedAsync<T>(GetConfigurationItemInput input)
        {
            var configDto = await GetByKeyAsync(input);

            try
            {
                // 处理空值
                if (configDto.Value == null)
                {
                    return default(T)!;
                }

                // 根据类型进行转换
                var targetType = typeof(T);
                var value = configDto.Value;

                if (targetType == typeof(string))
                {
                    return (T)(object)value;
                }
                else if (targetType == typeof(int) || targetType == typeof(int?))
                {
                    if (int.TryParse(value, out var intValue))
                    {
                        return (T)(object)intValue;
                    }
                }
                else if (targetType == typeof(long) || targetType == typeof(long?))
                {
                    if (long.TryParse(value, out var longValue))
                    {
                        return (T)(object)longValue;
                    }
                }
                else if (targetType == typeof(bool) || targetType == typeof(bool?))
                {
                    if (bool.TryParse(value, out var boolValue))
                    {
                        return (T)(object)boolValue;
                    }
                }
                else if (targetType == typeof(decimal) || targetType == typeof(decimal?))
                {
                    if (decimal.TryParse(value, out var decimalValue))
                    {
                        return (T)(object)decimalValue;
                    }
                }
                else if (targetType == typeof(double) || targetType == typeof(double?))
                {
                    if (double.TryParse(value, out var doubleValue))
                    {
                        return (T)(object)doubleValue;
                    }
                }
                else if (targetType == typeof(Guid) || targetType == typeof(Guid?))
                {
                    if (Guid.TryParse(value, out var guidValue))
                    {
                        return (T)(object)guidValue;
                    }
                }
                else if (targetType == typeof(DateTime) || targetType == typeof(DateTime?))
                {
                    if (DateTime.TryParse(value, out var dateTimeValue))
                    {
                        return (T)(object)dateTimeValue;
                    }
                }

                // 尝试使用JSON序列化处理复杂类型
                try
                {
                    return System.Text.Json.JsonSerializer.Deserialize<T>(value)!;
                }
                catch (System.Text.Json.JsonException)
                {
                    _logger.LogWarning("无法将配置值转换为指定类型: {Key}, Type: {Type}, Value: {Value}",
                        input.Key, targetType.Name, value);
                    return default(T)!;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取类型化配置时发生错误: {Key}, Type: {Type}", input.Key, typeof(T).Name);
                throw;
            }
        }

        /// <summary>
        /// 批量获取配置
        /// </summary>
        public async Task<Dictionary<string, ConfigurationItemDto>> GetBatchAsync(List<GetConfigurationItemInput> inputs)
        {
            if (inputs == null || inputs.Count == 0)
            {
                return new Dictionary<string, ConfigurationItemDto>();
            }

            var result = new Dictionary<string, ConfigurationItemDto>();
            var missingKeys = new List<GetConfigurationItemInput>();

            // 首先尝试从缓存获取 - 暂时跳过以避免类型不匹配
            // foreach (var input in inputs)
            // {
            //     var cacheKey = GetCacheKey(input.Key, input.Namespace);
            //     var cachedItem = await _cache.GetAsync(cacheKey);
            //
            //     if (cachedItem != null)
            //     {
            //         result[GetFullKey(input.Key, input.Namespace)] = cachedItem;
            //     }
            //     else
            //     {
            //         missingKeys.Add(input);
            //     }
            // }

            // 暂时将所有输入都标记为缺失，直接从数据库获取
            missingKeys = inputs;

            // 批量查询数据库中缺失的配置
            if (missingKeys.Count > 0)
            {
                var queryable = await _configurationRepository.GetQueryableAsync();
                var entities = await AsyncExecuter.ToListAsync(
                    queryable.Where(x => missingKeys.Any(m =>
                        x.Key == m.Key && x.Namespace == m.Namespace))
                );

                foreach (var entity in entities)
                {
                    var dto = ObjectMapper.Map<ConfigurationItem, ConfigurationItemDto>(entity);
                    var fullKey = GetFullKey(entity.Key, entity.Namespace);
                    result[fullKey] = dto;

                    // 缓存单个结果 - 使用不同类型的缓存或跳过缓存
                    // var cacheKey = GetCacheKey(entity.Key, entity.Namespace);
                    // var cacheOptions = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30) };
                    // await _cache.SetAsync(cacheKey, dto, cacheOptions); // 类型不匹配，暂时注释
                }
            }

            _logger.LogInformation("批量获取配置完成，请求数量: {RequestedCount}, 返回数量: {ResultCount}",
                inputs.Count, result.Count);

            return result;
        }

        /// <summary>
        /// 分页获取配置列表（保持与原有接口兼容）
        /// </summary>
        public async Task<PagedResultDto<ConfigurationItemDto>> GetListAsync(GetConfigurationItemListInput input)
        {
            var queryable = await _configurationRepository.GetQueryableAsync();

            // 应用过滤条件
            queryable = ApplyFilters(queryable, input);

            // 获取总数
            var totalCount = await AsyncExecuter.CountAsync(queryable);

            // 分页查询
            var items = await AsyncExecuter.ToListAsync(
                queryable.OrderBy(x => x.Namespace)
                    .ThenBy(x => x.Category)
                    .ThenBy(x => x.Key)
                    .PageBy(input.SkipCount, input.MaxResultCount)
            );

            var dtos = ObjectMapper.Map<List<ConfigurationItem>, List<ConfigurationItemDto>>(items);

            return new PagedResultDto<ConfigurationItemDto>(totalCount, dtos);
        }

        /// <summary>
        /// 通过ID获取配置项
        /// </summary>
        public async Task<ConfigurationItemDto> GetAsync(Guid id)
        {
            var entity = await _configurationRepository.GetAsync(id);
            return ObjectMapper.Map<ConfigurationItem, ConfigurationItemDto>(entity);
        }

        /// <summary>
        /// 清除指定配置的缓存
        /// </summary>
        public async Task ClearCacheAsync(string key, string @namespace = "")
        {
            var cacheKey = GetCacheKey(key, @namespace);
            await _cache.RemoveAsync(cacheKey);
            _logger.LogDebug("清除配置缓存: {CacheKey}", cacheKey);
        }

        /// <summary>
        /// 清除命名空间的所有缓存
        /// </summary>
        public async Task ClearNamespaceCacheAsync(string @namespace)
        {
            var namespaceCacheKey = $"namespace_configs:{@namespace}";
            await _cache.RemoveAsync(namespaceCacheKey);
            _logger.LogDebug("清除命名空间缓存: {Namespace}", @namespace);
        }

        #region 私有方法

        private static IQueryable<ConfigurationItem> ApplyFilters(IQueryable<ConfigurationItem> queryable, GetConfigurationItemListInput input)
        {
            if (!string.IsNullOrWhiteSpace(input.Namespace))
            {
                queryable = queryable.Where(x => x.Namespace.Contains(input.Namespace));
            }

            if (!string.IsNullOrWhiteSpace(input.Category))
            {
                queryable = queryable.Where(x => x.Category.Contains(input.Category));
            }

            if (!string.IsNullOrWhiteSpace(input.Key))
            {
                queryable = queryable.Where(x => x.Key.Contains(input.Key));
            }

            if (!string.IsNullOrWhiteSpace(input.Value))
            {
                queryable = queryable.Where(x => x.Value.Contains(input.Value));
            }

            if (!string.IsNullOrWhiteSpace(input.Description))
            {
                queryable = queryable.Where(x => x.Description != null && x.Description.Contains(input.Description));
            }

            if (input.DataTypes != null && input.DataTypes.Count > 0)
            {
                queryable = queryable.Where(x => input.DataTypes.Contains(x.DataType));
            }

            return queryable;
        }

        private static string GetCacheKey(string key, string @namespace)
        {
            return $"config_item:{@namespace}:{key}";
        }

        private static string GetFullKey(string key, string @namespace)
        {
            return string.IsNullOrWhiteSpace(@namespace) ? key : $"{@namespace}:{key}";
        }

        #endregion
    }
}